package com.weibo4j.api.authorize;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.script.Compilable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.weibo4j.api.util.HttpClientUtil;

public class SSO {

    private final static String SCRIPT      = "var RSAKey=new sinaSSOEncoder.RSAKey();RSAKey.setPublic('%s', '10001');password = RSAKey.encrypt('%s');";

    private final static String PRELOGINURL = "https://login.sina.com.cn/sso/prelogin.php?entry=openapi&callback=sinaSSOController.preloginCallBack&su=%s&rsakt=mod&client=ssologin.js(v1.4.1)&_=1344589404746";

    private final static String LOGINURL    = "https://login.sina.com.cn/sso/login.php?entry=openapi&gateway=1&from=&savestate=0&useticket=1&ct=1800&s=1&vsnf=1&vsnval=&door=&su=%s&service=miniblog&servertime=";

    private static ScriptEngine scriptEngine;

    static {
        try {
            init();
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void init() throws ScriptException, IOException {
        scriptEngine = new ScriptEngineManager().getEngineByName("javascript");
        InputStreamReader reader = new InputStreamReader(SSO.class.getClassLoader()
                .getResourceAsStream("sso.js"));
        Compilable compliable = (Compilable) scriptEngine;
        compliable.compile(reader).eval();
        reader.close();
    }

    public static String encrypt(String rsaPubKey, String password) throws ScriptException {
        String sc = String.format(SCRIPT, new Object[] { rsaPubKey, password });
        return scriptEngine.eval(sc).toString();
    }

    public static String loginAndGetTicket(String userName, String password) throws Exception {
        HttpClient client = HttpClientUtil.getHttpClient();
        userName = Base64.encodeBase64String(userName.getBytes());
        HttpGet getPubKeyReq = new HttpGet(String.format(PRELOGINURL, userName));
        HttpResponse getPubKeyResp = client.execute(getPubKeyReq);
        HttpEntity getPubKeyEntity = getPubKeyResp.getEntity();
        StringBuilder pubKeyStr = new StringBuilder();
        BufferedReader pubKeyReader = new BufferedReader(new InputStreamReader(
                getPubKeyEntity.getContent(), "utf-8"));
        String line = null;
        while ((line = pubKeyReader.readLine()) != null) {
            pubKeyStr.append(line);
        }
        pubKeyReader.close();
        String pubKey = pubKeyStr.toString().replace("sinaSSOController.preloginCallBack(", "")
                .replace(")", "");

        JSONObject obj = JSON.parseObject(pubKey);
        String servertime = obj.getString("servertime");
        String nonce = obj.getString("nonce");
        String rsakv = obj.getString("rsakv");
        String pubkey = obj.getString("pubkey");

        String enPwd = SSO.encrypt(pubkey, "12345");
        String loginUrl = String.format(LOGINURL, userName)
                + servertime
                + "&nonce="
                + nonce
                + "&pwencode=rsa&rsakv="
                + rsakv
                + "&sp="
                + enPwd
                + "&encoding=UTF-8&callback=sinaSSOController.loginCallBack&cdult=2&domain=weibo.com&prelt=110218&returntype=TEXT";

        HttpGet loginReq = new HttpGet(loginUrl);
        HttpResponse loginResp = client.execute(loginReq);
        HttpEntity loginRespEntity = loginResp.getEntity();
        StringBuilder loginStr = new StringBuilder();
        BufferedReader loginReader = new BufferedReader(new InputStreamReader(
                loginRespEntity.getContent(), "utf-8"));
        while ((line = loginReader.readLine()) != null) {
            loginStr.append(line);
        }
        loginReader.close();
        String ticketStr = loginStr.toString().replace("sinaSSOController.loginCallBack(", "")
                .replace(");", "");
        String ticket = JSON.parseObject(ticketStr).getString("ticket");
        return ticket;
    }
}
